home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / jovept2.arc / PROC.C < prev    next >
Text File  |  1985-05-30  |  11KB  |  521 lines

  1. /* proc.c */
  2.  
  3. /* JOVE/MSDOS. K. Mitchum 1/85 */
  4. /* Modifications for personal use only. */
  5. /* original code J. Payne LSRHS 5/83 */
  6. /* Ken Mitchum */
  7. /* University of Pittsburgh */
  8. /* Decision Systems Laboratory */
  9.  
  10. /*
  11.    Jonathan Payne at Lincoln-Sudbury Regional High School 5-25-83
  12.   
  13.    jove_proc.c
  14.  
  15.    This file contains procedures to handle the shell to buffer commands
  16.    and buffer to shell commands.  It isn't especially neat, but I think
  17.    it is understandable. */
  18.  
  19. #include "jove.h"
  20. #ifdef UNIX
  21. #include "whoami.h"
  22. #include <signal.h>
  23. #endif
  24.  
  25. extern int MakeAll;    /* funcs.h */
  26. extern int WtOnMk;    /* funcs.h */
  27.  
  28.  
  29. /*-------------------------o.s. dependent----------------------------*/
  30.  
  31. #ifdef UNIX
  32.  
  33. static char *MakeName();
  34.  
  35. static char *cerrfmt = "\\([^:]*\\):\\([0-9][0-9]*\\):";
  36.     /* C error scanf format string for errors of the form
  37.      * filename:linenum: error message
  38.      */
  39.  
  40. static char *lerrfmt = "\"\\([^:]*\\)\", line \\([0-9][0-9]*\\):";
  41.     /* Lint error for errors of the form
  42.      * "filename", line linenum: error message.
  43.      */
  44.  
  45. struct error {
  46.     BUFFER        *er_buf;    /* Buffer error is in */
  47.     LINE        *er_mess;    /* Actual error message */
  48.     LINE        *er_text;    /* Actual error */
  49.     int        er_char;    /* char pos of error */
  50.     struct error    *er_next;    /* List of error */
  51. };
  52.  
  53. static struct error *thiserror = 0,
  54.         *errorlist = 0;
  55. static BUFFER *thisbuf = 0;    /* Buffer that error parsing took place */
  56.  
  57.  
  58.  
  59. CParse()
  60. {
  61.     ErrParse(cerrfmt);
  62. }
  63.  
  64. LintParse()
  65. {
  66.     ErrParse(lerrfmt);
  67. }
  68.  
  69. /* Send the buffer to the spell program (for some reason, writing the 
  70.    file and running spell on that file caused spell to just sit there!)
  71.    and then go find each occurrence of the mispelled words that the user
  72.    says to go find.  Check out SpParse() */
  73.  
  74. SpellCom()
  75. {
  76.     WINDOW    *errwind,
  77.         *savewind;
  78.     char    command[100];
  79.  
  80.     savewind = curwind;
  81.     exp_p = 1;
  82.     if (IsModified(curbuf))
  83.         SaveFile();
  84.  
  85.     ignore(UnixToBuf("Spell", 1, !exp_p, "/bin/csh", "csh", "-cf",
  86.             sprintf(command, "/bin/spell %s", curbuf->b_fname), 0));
  87.     NotModified();
  88.     Bof();        /* Beginning of (error messages) file */
  89.     errwind = curwind;
  90.     if (linebuf[0]) {
  91.         SpParse(errwind, savewind);
  92.         if (thiserror)
  93.             NextError();
  94.         message("Go get 'em");
  95.     } else {
  96.         message("No errors");
  97.         SetWind(savewind);
  98.     }
  99. }
  100.  
  101. /* Go the the next error, if there is one.  Put the error buffer in
  102.    one window and the buffer with the error in another window.
  103.    It checks to make sure that the error actually exists. */
  104.  
  105. NextError()
  106. {
  107.     register int    i = exp;
  108.  
  109.     while (--i >= 0)
  110.         DoNextErr();
  111. }
  112.  
  113. /* Run make, first writing all the modified buffers (if the WtOnMk flag is
  114.  * non-zero), parse the errors, and go the first error.
  115.  */
  116.  
  117. MakeErrors()
  118. {
  119.     WINDOW    *old = curwind;
  120.     int    status;
  121.  
  122.     if (WtOnMk)
  123.         WtModBuf();
  124.     if (MakeAll)
  125.         status = UnixToBuf("make", 1, 1, "/bin/make", "Make", "-k", 0);
  126.     else
  127.         status = UnixToBuf("make", 1, 1, "/bin/make", "Make", 0);
  128.     com_finish(status, "make");
  129.     if (errorlist)
  130.         ErrFree();
  131.  
  132.     if (status)
  133. #ifndef VMUNIX
  134.         ErrParse(cerrfmt);
  135. #else
  136.         ErrParse(lerrfmt);
  137. #endif VMUNIX
  138.  
  139.     if (thiserror)
  140.         NextError();
  141.     else
  142.         SetWind(old);
  143. }
  144.  
  145. ShellCom()
  146. {
  147.     char    command[100];
  148.  
  149.     strcpy(command, ask((char *) 0, FuncName()));
  150.     DoShell(MakeName(command), command);
  151. }
  152.  
  153. /* Run the command to bufname, erase the buffer if clobber is non-zero,
  154.  * and redisplay if disp is non-zero.
  155.  */
  156.  
  157. /* VARARGS3 */
  158.  
  159. UnixToBuf(bufname, disp, clobber, func, args)
  160. char    *bufname,
  161.     *func;
  162. {
  163.     int    p[2],
  164.         pid;
  165.     char    buff[LBSIZE];
  166.     extern int    ninbuf;
  167.  
  168.     message("Starting up...");
  169.     pop_wind(bufname, clobber);
  170.     if (disp)
  171.         redisplay();        
  172.     if (clobber)
  173.         curbuf->b_type = SCRATCHBUF;
  174.     exp = 1;
  175.  
  176.     dopipe(p);
  177.     pid = fork();
  178.     if (pid == -1) {
  179.         PipeClose(p);
  180.         complain("Cannot fork");
  181.     }
  182.     if (pid == 0) {
  183.         ignorf(signal(SIGINT, SIG_DFL));
  184.  
  185.         ignore(close(0));
  186.         ignore(open("/dev/null", 0));
  187.         ignore(close(1));
  188.         ignore(close(2));
  189.         ignore(dup(p[1]));
  190.         ignore(dup(p[1]));
  191.         PipeClose(p);
  192.         execv(func, (char **) &args);
  193.         ignore(write(1, "Execl failed", 12));
  194.         _exit(1);
  195.     } else {
  196.  
  197.  
  198.  
  199.         int    (*oldquit)() = signal(SIGINT, SIG_IGN);
  200.  
  201.         int    status;
  202.         char    *mess;
  203.  
  204.         ignore(close(p[1]));
  205.         io = p[0];
  206.         while (getfline(buff) != EOF) {
  207.             ins_str(buff);
  208.             LineInsert();
  209.             if (ninbuf <= 0) {
  210. #ifdef VMUNIX            /* No easy way to find out */
  211.                 mess = "Chugging along...";
  212. #else
  213. #if    defined(MENLO_JCL) && !defined(NONFP)
  214.                 {
  215.                     short    avg[3];
  216.                     double    theavg;
  217.  
  218.                     ignore(gldav(avg));
  219.                     theavg = (double) avg[0] / 256;
  220.                     if (theavg < 1.0)
  221.                         mess = "Screaming along...";
  222.                     else if (theavg < 3.0)
  223.                         mess = "Chugging along...";
  224.                     else
  225.                         mess = "Crawling along...";
  226.                 }
  227. #else
  228.                 mess = "Chugging along...";
  229. #endif MENLO_JCL
  230. #endif VMUNIX
  231.                 message(mess);
  232.                 redisplay();
  233.             }
  234.         }
  235.         UpdateMesg();
  236.         IOclose();
  237.  
  238.  
  239.  
  240.         ignorf(signal(SIGINT, oldquit));
  241.  
  242.         while (wait(&status) != pid)
  243.             ;
  244.         return status;
  245.     }
  246.     return 0;
  247. }
  248.  
  249. /* Send a region to shell.  Now we can beautify C and sort programs */
  250.  
  251. RegToShell()
  252. {
  253.     char    com[100];
  254.     MARK    *m = CurMark();
  255.  
  256.     strcpy(com, ask((char *) 0, FuncName()));
  257.     if (!exp_p) {
  258.         exp_p = 1;    /* So it doesn't delete the region */
  259.         exp = 0;
  260.     }
  261.     if (inorder(m->m_line, m->m_char, curline, curchar))
  262.         RegToUnix(curbuf->b_name, 1, m->m_line, m->m_char,
  263.                     curline, curchar, com);
  264.     else
  265.         RegToUnix(curbuf->b_name, 1, curline, curchar, m->m_line,
  266.                     m->m_char, com);
  267.     message("Done");
  268. }
  269.  
  270. /* Add an error to the end of the list of errors.  This is used for
  271.  * parse-C/LINT-errors and for the spell-buffer command
  272.  */
  273.  
  274. static struct error *
  275. AddError(newerror, errline, buf, line, charpos)
  276. struct error    *newerror;
  277. LINE    *errline,
  278.     *line;
  279. BUFFER    *buf;
  280. {
  281.     if (newerror) {
  282.         newerror->er_next = (struct error *)
  283.                 emalloc(sizeof (struct error));
  284.         newerror = newerror->er_next;
  285.     } else
  286.         thiserror = newerror = errorlist = (struct error *)
  287.                 emalloc(sizeof (struct error));
  288.     newerror->er_buf = buf;
  289.     newerror->er_text = line;
  290.     newerror->er_char = charpos;
  291.     newerror->er_next = 0;
  292.     newerror->er_mess = errline;
  293.     return newerror;
  294. }
  295.  
  296. /* Returns the num'th line in buffer `b' */
  297.  
  298. static LINE *
  299. LineAt(num, b)
  300. register int    num;
  301. BUFFER     *b;
  302. {
  303.     register LINE    *lp = b->b_zero;
  304.  
  305.     while (--num > 0 && lp)
  306.         lp = lp->l_next;
  307.     return lp;
  308. }
  309.  
  310. /* Parse for C/LINT errors in the current buffer.  Set up for the next-error
  311.    command. */
  312.  
  313. static ErrParse(fmtstr)
  314. char    *fmtstr;
  315. {
  316.     BUFLOC    *bp;
  317.     char    fname[100],
  318.         lineno[10];
  319.     struct error    *ep = 0;
  320.     BUFFER    *buf;
  321.     
  322.     Bof();
  323.     if (errorlist)
  324.         ErrFree();
  325.     thisbuf = curbuf;
  326.     /* Find a line with a number on it */
  327.     while (bp = dosearch(fmtstr, 1, 1)) {
  328.         SetDot(bp);
  329.         putmatch(1, fname, sizeof fname);
  330.         putmatch(2, lineno, sizeof lineno);
  331.         buf = do_find((WINDOW *) 0, fname);
  332.         ep = AddError(ep, curline, buf, LineAt(atoi(lineno), buf), 0);
  333.     }
  334. }
  335.  
  336.  
  337. /* There is one word per line in the current buffer.  Read that word
  338.    and ask the user whether he wants us to search for it (if it is a
  339.    big buffer he may not want to if he thinks it is spelled correctly). */
  340.  
  341. static SpParse(err, buf)
  342. WINDOW    *err,
  343.     *buf;
  344. {
  345.     BUFLOC    *bp;
  346.     char    string[100],
  347.         ans;
  348.     struct error    *newerr = 0;
  349.  
  350.     if (errorlist)
  351.         ErrFree();
  352.     thisbuf = err->w_bufp;
  353.     SetWind(err);
  354.     for (;;) {
  355.         if (linebuf[0] == 0)
  356.             goto nextword;
  357.         s_mess("Is \"%s\" misspelled (Y or N)? ", linebuf);
  358.         ignore(sprintf(string, "\\b%s\\b", linebuf));
  359.         SetWind(buf);        /* Paper buffer */
  360.         Bof();
  361.         do
  362.             ans = getch();
  363.         while ((ans = Upperc(ans)) != 'Y' && ans != 'N');
  364.  
  365.         if (ans == 'Y') {    /* Not correct */
  366.             while (bp = dosearch(string, 1, 1)) {
  367.                 SetDot(bp);
  368.                 newerr = AddError(newerr, 
  369.                     thisbuf->b_dot, buf->w_bufp,
  370.                     curline, curchar);
  371.             }
  372.         }
  373.             
  374. nextword:
  375.         SetWind(err);    /* Back to error window to move to
  376.                    the next word */
  377.         if (eobp())
  378.             break;
  379.         if (ans == 'N') {    /* Delete the word ... */
  380.             Bol();
  381.             DoTimes(KillEOL, 1);    /* by deleting the line */
  382.         } else {
  383.             if (lastp(curline))
  384.                 break;
  385.             else
  386.                 SetLine(curline->l_next);
  387.         }
  388.     }
  389. }
  390.  
  391. /* Free up all the errors */
  392.  
  393. static ErrFree()
  394. {
  395.     register struct error    *ep;
  396.  
  397.     for (ep = errorlist; ep; ep = ep->er_next)
  398.         free((char *) ep);
  399.     errorlist = thiserror = 0;
  400. }
  401.  
  402.  
  403. static DoNextErr()
  404. {
  405.     /* Make sure we haven't deleted the line with the actual error
  406.        by accident. */
  407.  
  408.     while (errorlist && thiserror) {
  409.         if (inlist(thiserror->er_buf->b_zero, thiserror->er_text))
  410.             break;
  411.         thiserror = thiserror->er_next;
  412.     }
  413.     if (errorlist == 0 || thiserror == 0)
  414.         complain("No errors");
  415.  
  416.     pop_wind(thisbuf->b_name, 0);
  417.     SetLine(thiserror->er_mess);
  418.     SetTop(curwind, (curwind->w_line = thiserror->er_mess));
  419.     pop_wind(thiserror->er_buf->b_name, 0);
  420.     DotTo(thiserror->er_text, thiserror->er_char);
  421.     thiserror = thiserror->er_next;
  422. }
  423.  
  424.  
  425. /* Make a buffer name given the command `command', i.e. "fgrep -n foo *.c"
  426.    will return the buffer name "fgrep".  */
  427.  
  428. static char *
  429. MakeName(command)
  430. char    *command;
  431. {
  432.     static char    bufname[50];
  433.     char    *cp = bufname, c;
  434.  
  435.     while ((c = *command++) && (c == ' ' || c == '\t'))
  436.         ;
  437.     do
  438.         *cp++ = c;
  439.     while ((c = *command++) && (c != ' ' && c != '\t'));
  440.     *cp = 0;
  441.     cp = rindex(bufname, '/');
  442.     if (cp)
  443.         strcpy(bufname, cp + 1);
  444.     return bufname;
  445. }
  446.  
  447. ShToBuf()
  448. {
  449.     char    bufname[100];
  450.  
  451.     strcpy(bufname, ask((char *) 0, "Buffer: "));
  452.     DoShell(bufname, ask((char *) 0, "Command: "));
  453. }
  454.  
  455. /* Run the shell command into `bufname'.  Empty the buffer except when we
  456.    give a numeric argument, in which case it inserts the output at the
  457.    current position in the buffer.  */
  458.  
  459. static DoShell(bufname, command)
  460. char    *bufname,
  461.     *command;
  462. {
  463.     WINDOW    *savewp = curwind;
  464.     int    status;
  465.  
  466.     exp = 1;
  467.     status = UnixToBuf(bufname, 1, !exp_p, "/bin/csh", "csh", "-fc",
  468.             command, 0);
  469.     com_finish(status, command);
  470.     SetWind(savewp);
  471. }
  472.  
  473. static com_finish(status, com)
  474. char    *com;
  475. {
  476.     s_mess("\"%s\" completed %ssuccessfully", com, status ? "un" : "");
  477. }
  478.  
  479. static dopipe(p)
  480. int    p[];
  481. {
  482.     if (pipe(p) == -1)
  483.         complain("Cannot pipe");
  484. }
  485.  
  486. static PipeClose(p)
  487. int    p[];
  488. {
  489.     ignore(close(p[0]));
  490.     ignore(close(p[1]));
  491. }
  492.  
  493. /* Writes the region to a tmp file and then run the command with input
  494.    from that file */
  495.  
  496. static RegToUnix(bufname, replace, line1, char1, line2, char2, func)
  497. char    *bufname;
  498. LINE    *line1,
  499.     *line2;
  500. char    *func;
  501. {
  502.     char    *fname = mktemp(TMPFILE);
  503.     char    com[100];
  504.  
  505.     if ((io = creat(fname, 0644)) == -1)
  506.         complain(IOerr("create", fname));
  507.     putreg(line1, char1, line2, char2);
  508.     IOclose();
  509.     if (replace)
  510.         DelReg();
  511.     ignore(sprintf(com, "%s < %s", func, fname));
  512.     ignore(UnixToBuf(bufname, 0, 0, "/bin/csh", "csh", "-c", com, 0));
  513.     ignore(unlink(fname));
  514. }
  515.  
  516. #endif
  517.  
  518. /* clone */
  519.  
  520. /* end */
  521.